package com.sxhuayuan.parking.compenent;

import java.util.HashMap;
import java.util.Map;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import com.sxhuayuan.parking.queue.rabbitmq.RabbitMQ;

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class RabbitMQConfig {

	/** 延迟消息入口路由，全匹配模式，要实现延时的业务队列都可绑定到它，通过此路由来实现延迟发布消息 */
	public final static String EXCHANGE_DELAY_START = "exchange.delay.start";

	/** 延时队列的死信队列，延时消息消费失败时进入此队列，此队列的消费者处理下一次延迟时间再放回对应延时队列 */
	public final static String QUEUE_DELAY_DLX = "queue.delay.dlx";
	/** 延时队列的死信路由，绑定QUEUE_DELAY_DLX队列 */
	public final static String EXCHANGE_DELAY_DLX = "exchange.delay.dlx";

	/** 最终死信队列 */
	public final static String QUEUE_FINAL_DLX = "queue.final.dlx";
	/** 最终死信路由 */
	public final static String EXCHANGE_FINAL_DLX = "exchange.final.dlx";

	/* --业务队列--start */
	/** 委托代扣消息队列 */
	public final static String QUEUE_DELAY_PARTNERPAY = "queue.delay.partnerpay";
	/** 入场消息队列 */
	public final static String QUEUE_PARK_IN = "queue.parkIn";
	/** 通知第三方车场消息队列 */
	public final static String QUEUE_DELAY_NOTIFY_PARKING_LOT = "queue.delay.notifyParkingLot";
	// 在这里声明队列名
	// ...

	/* --业务队列--end */

	@Bean(EXCHANGE_DELAY_START)
	public Exchange exchangeDelay() {
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("x-delayed-type", ExchangeTypes.DIRECT);
		CustomExchange ex = new CustomExchange(EXCHANGE_DELAY_START, "x-delayed-message", true, false, args);
		return ex;
	}

	@Bean(EXCHANGE_DELAY_DLX)
	public Exchange exchangeDelayDlx() {
		return new DirectExchange(EXCHANGE_DELAY_DLX);
	}

	@Bean(QUEUE_DELAY_DLX)
	public Queue queueDelayDLX() {
		return QueueBuilder.durable(QUEUE_DELAY_DLX)

				.withArgument(RabbitMQ.X_DEAD_LETTER_EXCHANGE, EXCHANGE_FINAL_DLX)

				.withArgument(RabbitMQ.X_DEAD_LETTER_ROUTING_KEY, QUEUE_FINAL_DLX).build();
	}

	@Bean(EXCHANGE_FINAL_DLX)
	public Exchange exchangeFinalDLX() {
		return new DirectExchange(EXCHANGE_FINAL_DLX);
	}

	@Bean(QUEUE_FINAL_DLX)
	public Queue queueFinalDLX() {
		return new Queue(QUEUE_FINAL_DLX, true, false, false);
	}

	@Bean
	Binding bindingFinalDlx(@Qualifier(QUEUE_FINAL_DLX) Queue queueFinalDLX, @Qualifier(EXCHANGE_FINAL_DLX) DirectExchange dlxFinalExchange) {
		return BindingBuilder.bind(queueFinalDLX).to(dlxFinalExchange).with(QUEUE_FINAL_DLX);
	}

	@Bean(QUEUE_DELAY_PARTNERPAY)
	public Queue queuePartnerpay() {
		return QueueBuilder.durable(QUEUE_DELAY_PARTNERPAY)
				// 指定死信交换机
				.withArgument(RabbitMQ.X_DEAD_LETTER_EXCHANGE, EXCHANGE_DELAY_DLX)
				// 指定死信路由键值（x-dead-letter-routing-key）
				.withArgument(RabbitMQ.X_DEAD_LETTER_ROUTING_KEY, QUEUE_DELAY_DLX).build();
	}

	@Bean(QUEUE_PARK_IN)
	public Queue queueParkIn() {
		return QueueBuilder.durable(QUEUE_PARK_IN)
				// 指定死信交换机
				.withArgument(RabbitMQ.X_DEAD_LETTER_EXCHANGE, EXCHANGE_FINAL_DLX)
				// 指定死信路由键值（x-dead-letter-routing-key）
				.withArgument(RabbitMQ.X_DEAD_LETTER_ROUTING_KEY, QUEUE_FINAL_DLX).build();
	}

	// 延迟队列
	@Bean(QUEUE_DELAY_NOTIFY_PARKING_LOT)
	public Queue queueNotifyParkingLot() {
		return QueueBuilder.durable(QUEUE_DELAY_NOTIFY_PARKING_LOT).withArgument(RabbitMQ.X_DEAD_LETTER_EXCHANGE, EXCHANGE_DELAY_DLX)
				.withArgument(RabbitMQ.X_DEAD_LETTER_ROUTING_KEY, QUEUE_DELAY_DLX).build();
	}

	// 在这里配置队列dlx ...
	// ...

	// 绑定死信路由和死信队列
	@Bean
	Binding bindingDelayDlx(@Qualifier(QUEUE_DELAY_DLX) Queue queuePartnerpay, @Qualifier(EXCHANGE_DELAY_DLX) DirectExchange exchangeDlx) {
		return BindingBuilder.bind(queuePartnerpay).to(exchangeDlx).with(QUEUE_DELAY_DLX);
	}

	// 绑定业务队列和延时路由，经过延时路由才能延时后到达业务队列用来消费
	@Bean
	Binding bindingPartnerpayQueue(@Qualifier(QUEUE_DELAY_PARTNERPAY) Queue queueDelay, @Qualifier(EXCHANGE_DELAY_START) CustomExchange exchangeDelay) {
		return BindingBuilder.bind(queueDelay).to(exchangeDelay).with(QUEUE_DELAY_PARTNERPAY).noargs();
	}

	/** 通知车场消息队列 */
	@Bean
	Binding bindingNotifyParkingLotQueue(@Qualifier(QUEUE_DELAY_NOTIFY_PARKING_LOT) Queue queueDelay, @Qualifier(EXCHANGE_DELAY_START) CustomExchange exchangeDelay) {
		return BindingBuilder.bind(queueDelay).to(exchangeDelay).with(QUEUE_DELAY_NOTIFY_PARKING_LOT).noargs();
	}

	@Bean
	Binding bindingParkInQueue(@Qualifier(QUEUE_PARK_IN) Queue queueParkIn, @Qualifier(EXCHANGE_DELAY_START) CustomExchange exchangeDelay) {
		return BindingBuilder.bind(queueParkIn).to(exchangeDelay).with(QUEUE_PARK_IN).noargs();
	}

}
